#include <iostream>
#include <stdlib.h>

#include <nemesis.Logger.h>

#include <nemesis.dbms.Connection.h>
#include <nemesis.dbms.Database.h>
#include <nemesis.dbms.Statement.h>

#include <nemesis.dbos.AutoObject.h>

#include <dbos_demo.defines.h>

#include <dbos_demo.oodb.Table01.h>

#include <dbos_demo.phase.CanNotReload.h>

using namespace std;
using namespace nemesis;
using namespace dbos_demo;

void phase::CanNotReload::do_comment () const
   throw ()
{
   cout << "Carga un registro, lo borra, lo recarga e inntenta seguir usandolo, pero se obtendra una excepcion;" << endl;
   cout << "el objeto queda marcado como 'incoherent' y en cuanto su cuenta de utilizacion sea 0, se " << endl;
   cout << "destruira la proxima vez que se intente cargar el circuito de error es mas corto ya qu no." << endl;
   cout << "esta registrado como disponible en memoria" << endl;
   cout << "Volvemos a cargar una serie de registros y verificamos que el hueco reusado no se vuelve a destruir" << endl;
}

// (1) Ejecuta una sentencia SQL erronea para generar un rollback y recuperar el registro borrado.
void phase::CanNotReload::do_apply (dbms::Connection& connection)
   throw (RuntimeException, dbms::DatabaseException)
{
   using namespace nemesis::dbms;

   Guard guard (connection);

   const int id (rand () % MaxKey01);
   
   dbos::AutoObject <oodb::Table01> table01;

   { // Para provocar que el registro este en cache despues de borrarlo.
      dbos::AutoObject <oodb::Table01> table01;
   
      table01 = oodb::Table01::instanciate (connection, id);
       
      LOGINFORMATION (
         string msg (table01->asString ());
         msg += " | Primera carga";      
         Logger::information (msg, FILE_LOCATION);
      );
   }
   
   Database& database = connection.getDatabase ();
   
   Statement* statement = database.createStatement (
      "_reload_delete_", functions::asString ("delete nemesis_db_table01 where key=%d", id)
   );
   ResultCode resultCode = connection.execute (statement);
   if (resultCode.successful () == false)
      throw DatabaseException (resultCode, FILE_LOCATION);
   
   try {
      LOGINFORMATION (
         Logger::information (functions::asString ("Primero intento instanciar %d", id), FILE_LOCATION);
      );
      table01 = oodb::Table01::instanciate (connection, id);
   }
   catch (Exception& ex) {
      ex.trace ();
   }

   try {
      LOGINFORMATION (
         Logger::information (functions::asString ("Segundo intento instanciar %d", id), FILE_LOCATION);
      );
      table01 = oodb::Table01::instanciate (connection, id);
   }
   catch (Exception& ex) {
      ex.trace ();
   }

   try {           
      int id2;
      for (int i = 0; i < 20; i ++) {
         id2 = rand () % MaxKey01;
   
         table01 = oodb::Table01::instanciate (connection, id2);

         LOGINFORMATION (
            string msg (table01->asString ());
            msg += " | Otro registro";
            Logger::information (msg, FILE_LOCATION);
         );   
      }
   }
   catch (Exception& ex) {
      ex.trace ();
   }
   
   statement = database.createStatement ("_reload_generate_rollback", "__that_is_an_invalid_statement");
   connection.execute (statement);   // (1)
}

 

